package com.teamone.etl.util;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * @author Mr.Fu
 * @date 2021/1/12 19:10
 */
public class CreateFileUtil {
    /**
     *获取本地java代码路径
     */
    static String javaPath = Thread.currentThread().
                            getContextClassLoader().
                            getResource("com/teamone/etl/dataruleengine").
                            toString().
                            replace("file:/", "");

    /**
     * 获取本地sql文件路径
     */
    static String sqlPath = Thread.currentThread().
                            getContextClassLoader().
                            getResource("com/teamone/etl/dataruleengine").
                            toString().
                            replace("file:/", "");

    static File javaFile = null;

    static File sqlFile = null;

    /**
     * 获取java文件
     * @param functionName
     * @return
     * @throws IOException
     */
    public static File getJavaFile(String functionName) {
        //拼接java路径
        javaFile = new File(javaPath + "/rule/" + functionName + ".java");

        if(!javaFile.exists()) {
            try {
                //创建该文件
                javaFile.createNewFile();

            }catch(IOException e){
                e.printStackTrace();
            }
        }else {
            //删除该文件
            javaFile.delete();
            System.gc();
        }
        return javaFile;
    }

    /**
     * 获取class文件
     * @param functionName
     * @return
     * @throws IOException
     */
    public static File getClassFile(String functionName) {
        //拼接java路径
        javaFile = new File(javaPath + "/" + functionName + ".class");

        return javaFile;
    }


    /**
     * 获取sql文件
     * @param functionName
     * @return
     * @throws IOException
     */
    public static File getSqlFile(String functionName) throws IOException {
        //拼接sql路径
        sqlFile = new File(sqlPath + "/database/" + functionName + ".sql");
        if(!sqlFile.exists()) {
            try {
                //创建该文件
                sqlFile.createNewFile();
            }catch(IOException e){
                e.printStackTrace();
            }
        }else {
            //删除该文件
            sqlFile.delete();
            System.gc();
        }
        return sqlFile;
    }

    /**
     * 将文件放入缓冲输出流中
     * @param file
     * @return
     * @throws IOException
     */
    private static BufferedWriter getBw(File file) throws IOException {
        return new BufferedWriter(new FileWriter(file));
    }

    /**
     * 初始化java文件内容
     * @param functionName
     * @return
     * @throws IOException
     */
    public static String initializeFile(String functionName) throws IOException {
        String javaLu = "package com.teamone.etl.dataruleengine.rule";
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(javaFile));
        String codes = javaLu+";"+"\n"+"public class"+" "+functionName+"{"+"\n\n"+"}";
        bufferedWriter.write(codes);
        bufferedWriter.flush();
        bufferedWriter.close();
        return codes;
    }

    /**
     * 编译java文件
     * @param functionName
     * @return
     * @throws IOException
     */
    public static Integer createFile(String functionName) {

        File htmlFile = getJavaFile(functionName);
        //自定义类加载器并编译java源文件
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        String s1 = htmlFile.toString();
        int result = compiler.run(null, null, null, s1);
        System.out.println(result == 0 ? "编译成功" : "编译失败");
        return result;

    }

    /**
     * 运行java文件
     * @param functionName  类/函数名字
     * @param codes         代码内容
     * @return
     * @throws IOException
     */
    public static String updateFile(String functionName,String codes) throws IOException {
        //标识runtime是否已经编译
        Integer flag = 0;
        //创建缓冲输入流，将文件放到缓冲区里
        File htmlFile = getJavaFile(functionName);

        try (BufferedWriter bw = getBw(htmlFile)) {
            bw.write(codes);
            bw.flush();
        } finally {
            /*
             * 后置处理代码，无论异常是否被捕获，finally的代码一定会被执行。
             * 自定义类加载器并编译java源文件
             */
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            String s1 = htmlFile.toString();
            int result = compiler.run(null, null, null, s1);
            System.out.println(result == 0 ? "编译成功" : "编译失败");

            //Runtime调用编译类
            Runtime run=Runtime.getRuntime();
            String replace = s1.replace("\\","/");
            String replace1 = replace.replace(functionName + ".java", " ");
            Process process = run.exec("java -cp " + replace1 + functionName);
            InputStream in=process.getInputStream();
            BufferedReader bw1=new BufferedReader(new InputStreamReader(in));
            String info;
            while((info=bw1.readLine())!=null){
                System.out.println(info);
                flag = 1;
            }
            //类加载器调用编译类  如果Runtime无法编译 就用类加载器
            if(flag==0){
                URL[] urls = new URL[]{new URL("file:/" + replace1 + "/")};
                URLClassLoader loader = new URLClassLoader(urls);
                try {
                    Class c = loader.loadClass(functionName);
                    c.getMethod("demo").invoke(c.newInstance());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return codes;

    }

}
